package com.zan.callable;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @Author Zan
 * @Create 2024/3/1 8:58
 * @Description : 比较Runnable和Callable两个接口
 */
public class Demo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // Runnable 接口创建线程
        new Thread(new MyThread1(), "AA").start();

        // Callable接口创建线程, 报错
//        new Thread(new MyThread2(), "BB").start();

        // FutureTask
        FutureTask<Integer> futureTask1 = new FutureTask<>(new MyThread2());

        // lambda表达式
        FutureTask<Integer> futureTask2 = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + " come in callable");
            return 1024;
        });
        FutureTask<Integer> futureTask3 = new FutureTask<>(() -> 1024);

        // 创建一个线程
        new Thread(futureTask2, "lucy").start();
        new Thread(futureTask1, "mary").start();

        // isDone()表示计算是否完成
//        while (!futureTask2.isDone()) {
//            System.out.println("wait..........");
//        }

        // 调用FutureTask的get方法，获取返回结果
        System.out.println(futureTask2.get());

        // 使用未来任务只会执行一次，第二次就直接获取值了
//        System.out.println(futureTask2.get());
        System.out.println(futureTask1.get()); // 200

        System.out.println(Thread.currentThread().getName() + " come over");

        // FutureTask原理 未来任务（在主线程不影响的情况下，单开一个线程；主线程要用的时候，直接去那里拿、得到）
        /**
         * 1. 老师上课，口渴了，去买水不合适，讲课线程继续
         *    单开启线程找班上班长帮我去买水
         *    把水买回来，需要的时候直接get
         *
         * 2. 4个同学分别做计算，1同学 1+2...5  , 2同学 10+11+12...50  , 3同学 60+61+62  , 4同学 100+200
         *    第2个同学计算量比较大，
         *    FutureTask单开启线程给第2个同学计算，先汇总1 3 4，最后等2同学计算完成，统一汇总
         *
         * 3. 考试，做会做的题目，最后看不会做的题目
         *
         * 汇总一次
         *
         */

    }
}

// 实现Runnable接口
class MyThread1 implements Runnable {

    @Override
    public void run() {

    }
}

// 实现Callable接口
class MyThread2 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName() + " come in callable");
        return 200;
    }
}